/**************************************************************************(C)*
 *
 *  This file is part of the GreenHills project
 *  Copyright (C) 2009  TietoEnator
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************(C)*/

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "logindialog.h"
#include "gpstestwidget.h"
#include "compas/compas.h"

#include "../util/serialport.h"
#include "../util/lineterminal.h"
#include "../util/binstream.h"
#include "../util/memstreambuf.h"
#include "../gps/nmeaparser.h"
#include "../gps/gps.h"

#include "../util/conversion.h"

#include "../core/serverproxy.h"
#include "../core/room.h"
#include "../core/localuser.h"


#include <QtCore/QTimer>

#define DEFAULT_USERNAME_NAME "FerdaMravenec"
#define DEFAULT_HOST_NAME "localhost"
#define DEFAULT_UPDATE_PERIOD_SEC 5

using namespace client;
using namespace util;
using namespace gps;

CMainWindow::CMainWindow(QWidget *pParent) :
    QMainWindow(pParent),
    mUi(new Ui::CMainWindow), mRoom(0)
{
    mUi->setupUi(this);

    mSerialPort = CSerialPort::instance();
    mLineTerminal = new CLineTerminal(QApplication::instance());
    mNmeaParser = new CNMEAParser(QApplication::instance());
    QObject::connect(mSerialPort, SIGNAL(dataReceived(QByteArray)),
                     mLineTerminal, SLOT(onDataReceived(QByteArray)));
    QObject::connect(mLineTerminal, SIGNAL(lineReceived(QString)),
                     mNmeaParser, SLOT(onLineReceived(QString)));

    mGpsTestWidget = new CGPSTestWidget(
            mSerialPort, mLineTerminal, mNmeaParser, this);


    mGps = new CGPS(this);
    QObject::connect(
        mNmeaParser, SIGNAL(GPGGAreceived(QTime,gps::CGPSPosition,gps::CGPSFix,int,float,float,float,float,int)),
        mGps, SLOT(onGPGGAreceived(QTime,gps::CGPSPosition,gps::CGPSFix,int,float,float,float,float,int)));
    QObject::connect(
        mNmeaParser, SIGNAL(GPVTGreceived(float,float,float,float)),
        mGps, SLOT(onGPVTGreceived(float,float,float,float)));


    mUi->tabWidget->clear();
    mUi->tabWidget->addTab(mGpsTestWidget,"GPS Test");
    //this->setCentralWidget(mGpsTestWidget);

    mCompas = new CCompas(this);
    mUi->tabWidget->addTab(mCompas,"Compass");
    QObject::connect(mGps, SIGNAL(movementDirectionChanged(int)),
        mCompas, SLOT(onDirectionToTargetChanged(int)));

    QTimer *submitPositionTimer = new QTimer(this);
    submitPositionTimer->setInterval(DEFAULT_UPDATE_PERIOD_SEC * 1000);
    QObject::connect(submitPositionTimer, SIGNAL(timeout()),
                     this, SLOT(onSubmitPositionTimerFired()));
    submitPositionTimer->start();
}

CMainWindow::~CMainWindow()
{
    delete mUi;
}

void CMainWindow::on_actionConnect_triggered()
{
    CServerProxy::instance()->connect(DEFAULT_HOST_NAME);
}

void CMainWindow::on_actionDisconnect_triggered()
{
    CServerProxy::instance()->disconnect();
}

void CMainWindow::on_actionLogin_triggered()
{
    CLoginDialog loginDialog(this,DEFAULT_USERNAME_NAME);
    if (loginDialog.exec() == QDialog::Accepted)
    {
        CServerProxy::instance()->login(qstr2std(loginDialog.userName()),
                                        qstr2std(loginDialog.password()));
    }
}

void CMainWindow::on_actionLogout_triggered()
{
    CServerProxy::instance()->logout();
}

void CMainWindow::on_actionCreate_triggered()
{
    CServerProxy::instance()->createRoom("Default",0);
}

void CMainWindow::on_actionJoin_triggered()
{
    if (CServerProxy::instance()->joinRoom(DEFAULT_ROOM_ID))
    {
        core::CItemId itemId = CServerProxy::instance()->addItem(
                DEFAULT_ROOM_ID, DEFAULT_USERNAME_NAME, core::itUser);

        mRoom = new CRoom(DEFAULT_ROOM_ID, "DEFAULT_ROOM_NAME", itemId, this);

        mRoom->addItem(itemId, DEFAULT_USERNAME_NAME, core::itUser);

        const CLocalUser *localUser =
                dynamic_cast<const CLocalUser*>(mRoom->item(itemId));

        Q_ASSERT(localUser);

        QObject::connect(
            mNmeaParser,
            SIGNAL(GPGGAreceived(QTime,gps::CGPSPosition,gps::CGPSFix,int,float,float,float,float,int)),
            localUser,
            SLOT(onGPGGAreceived(QTime,gps::CGPSPosition,gps::CGPSFix,int,float,float,float,float,int)));
        QObject::connect(
            mNmeaParser,
            SIGNAL(GPVTGreceived(float,float,float,float)),
            localUser,
            SLOT(onGPVTGreceived(float,float,float,float)));
    }

}

void CMainWindow::on_actionLeave_triggered()
{
    CServerProxy::instance()->leaveRoom(0);
    if (mRoom)
        delete mRoom;
}

void CMainWindow::onSubmitPositionTimerFired()
{
    if (mRoom)
    {
        const CLocalUser *localUser =
                dynamic_cast<const CLocalUser*>(mRoom->localUser());

        Q_ASSERT(localUser);

        memstreambuf buffer;
        obinstream os(&buffer);
        localUser->operator <<(os);
        CServerProxy::instance()->updateItem(mRoom->id(), localUser->id(),
            (const unsigned char*)buffer.data(), buffer.length());
    }
}
